﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Collections;

namespace DIP_LAB_KY
{
    public partial class Form1 : Form
    {
        #region INIT
        Image _CurrentImage = null;
        Image _EmptyImage = null;
        MyClass[,] _aryMy;

        int[,] iFilter = new int[5, 5];
        int iMax = 255;
        int iMin = 0;

        class MyClass
        {
            public int Counts;
            public Point[] Points;

            public MyClass()
            {             
                Counts = 0;             
                Points = new Point[500];
            }          
            public void AddPoint(int x, int y)
            {
                Points[Counts] = new Point();
                Points[Counts].X = x;
                Points[Counts].Y = y;
                Counts++;
            }
        }

        public Form1()
        {
            InitializeComponent();
            Init();
        }

        public void Init()
        {
            _CurrentImage = this.pictureBox1.Image;
            _EmptyImage = EmptyImage(_CurrentImage);
            this.pictureBox2.Image = _CurrentImage;
        }
        #endregion 

        #region Filter
        public int[,] GetFilter_LaplacianFilters4()
        {
            int[,] Filter = {
                            { 0,-1, 0},
                            {-1, 4,-1},
                            { 0,-1, 0}                            
                            };
            return Filter;
        }

        public int[,] GetFilter_LaplacianFilters8()
        {
            int[,] Filter = {
                            {-1,-1,-1},
                            {-1, 8,-1},
                            {-1,-1,-1}                            
                            };
            return Filter;
        }

        public int[,] GetFilter_Sharpen5()
        {
            int[,] Filter = {
                            { 0,-1, 0},
                            {-1, 5,-1},
                            { 0,-1, 0}                            
                            };
            return Filter;
        }
        public int[,] GetFilter_Sharpen9()
        {
            int[,] Filter = {
                            {-1,-1,-1},
                            {-1, 9,-1},
                            {-1,-1,-1}                            
                            };
            return Filter;
        }

        public int[,] GetFilter_Blur_3()
        {
            int[,] Filter = {
                            {  1, 1, 1 },
                            {  1, 1, 1 },
                            {  1, 1, 1 }                            
                            };
            return Filter;
        }
        public int[,] GetFilter_Blur_5()
        {
            int[,] Filter = {
                            {  1, 1, 1, 1, 1 },
                            {  1, 1, 1, 1, 1 },
                            {  1, 1, 1, 1, 1 },
                            {  1, 1, 1, 1, 1 },
                            {  1, 1, 1, 1, 1 }                            
                            };
            return Filter;
        }
        public int[,] GetFilter_SobelX()
        {
            int[,] Filter = {
                            { -1,-2, -1 },
                            {  0, 0,  0 },
                            {  1, 2,  1 }                            
                            };
            return Filter;
        }

        public int[,] GetFilter_SobelY()
        {
            int[,] Filter = {
                            { -1, 0,  1 },
                            { -2, 0,  2 },
                            { -1, 0,  1 }                            
                            };
            return Filter;
        }

        public void SetFilter()
        {
            /*
            * 1 2 3
            * 4 5 6
            * 7 8 9
            */
            iFilter[0, 0] = Convert.ToInt16(txtFilter1.Text);
            iFilter[0, 1] = Convert.ToInt16(txtFilter2.Text);
            iFilter[0, 2] = Convert.ToInt16(txtFilter3.Text);
            iFilter[0, 3] = Convert.ToInt16(txtFilter4.Text);
            iFilter[0, 4] = Convert.ToInt16(txtFilter5.Text);

            iFilter[1, 0] = Convert.ToInt16(txtFilter6.Text);
            iFilter[1, 1] = Convert.ToInt16(txtFilter7.Text);
            iFilter[1, 2] = Convert.ToInt16(txtFilter8.Text);
            iFilter[1, 3] = Convert.ToInt16(txtFilter9.Text);
            iFilter[1, 4] = Convert.ToInt16(txtFilter10.Text);

            iFilter[2, 0] = Convert.ToInt16(txtFilter11.Text);
            iFilter[2, 1] = Convert.ToInt16(txtFilter12.Text);
            iFilter[2, 2] = Convert.ToInt16(txtFilter13.Text);
            iFilter[2, 3] = Convert.ToInt16(txtFilter14.Text);
            iFilter[2, 4] = Convert.ToInt16(txtFilter15.Text);

            iFilter[3, 0] = Convert.ToInt16(txtFilter16.Text);
            iFilter[3, 1] = Convert.ToInt16(txtFilter17.Text);
            iFilter[3, 2] = Convert.ToInt16(txtFilter18.Text);
            iFilter[3, 3] = Convert.ToInt16(txtFilter19.Text);
            iFilter[3, 4] = Convert.ToInt16(txtFilter20.Text);

            iFilter[4, 0] = Convert.ToInt16(txtFilter21.Text);
            iFilter[4, 1] = Convert.ToInt16(txtFilter22.Text);
            iFilter[4, 2] = Convert.ToInt16(txtFilter23.Text);
            iFilter[4, 3] = Convert.ToInt16(txtFilter24.Text);
            iFilter[4, 4] = Convert.ToInt16(txtFilter25.Text);
        }

        #endregion 

        #region General Function     
        public Image PrintLineByTopN(Image SourceImage, int N)
        {
            Image TargetImage;
            int height = SourceImage.Height;
            int width = SourceImage.Width;
            Bitmap bimage = new Bitmap(SourceImage);            
            int[, ,] rgbDataA = getRGBData(SourceImage);

            MyClass[] AryPoint = new MyClass[N];
            for (int n = 0; n < N; n++)
            {
                int iPointMax = 0;
                int iX = 0;
                int iY = 0;
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        if (_aryMy[x, y] != null)
                        {
                            if (_aryMy[x, y].Counts > iPointMax)
                            {
                                iPointMax = _aryMy[x, y].Counts;
                                iX = x;
                                iY = y;
                            }
                        }
                    }
                }                
                AryPoint[n] = new MyClass();
                AryPoint[n] = _aryMy[iX, iY];
                _aryMy[iX, iY].Counts = 0;
            }


            for (int i = 0; i < N; i++)
            {
                #region find Max Min XY
                int iMinX = 1000000; int iMinY = 1000000;
                int iMaxX = -1 ;   int iMaxY = -1;
                bool cX = false;   bool cY = false;
                int iOldX = -1;    int iOldY = -1;
                int iCount = 0;
                double x1 =0, x2=0, y1=0, y2=0;
                foreach (Point p in AryPoint[i].Points)
                {
                    if (p.IsEmpty)
                    {
                        break;
                    }
                    else
                    {
                        if( iCount ==0)
                        {
                            x1= p.X;
                            y1 = p.Y;
                        }
                        if (iOldX != p.X)
                        {
                            if (iCount > 0) cX = true;
                        }
                        if (iOldY != p.Y)
                        {
                            if (iCount > 0) cY = true;
                        }
                        if (p.X < iMinX)
                        {
                            iMinX = p.X;
                        }
                        if (p.Y < iMinY)
                        {
                            iMinY = p.Y;
                        }
                        if (p.X > iMaxX)
                        {
                            iMaxX = p.X;
                        }
                        if (p.Y > iMaxY)
                        {
                            iMaxY = p.Y;
                        }
                        x2 = p.X;
                        y2 = p.Y;
                        iCount++;
                    }
                }
                #endregion

                double dx = x2-x1;
                double dy = y2-y1;
                double a = dy/dx;
                double b = (y1-a*x1);

                for (int x = iMinX; x < iMaxX; x++)
                {
                    for (int y = iMinY; y < iMaxY; y++)
                    {
                        double z = 0 ;
                        if (cX && cY)
                        {
                            z = (a * (double)x) + b;
                            if (y == Math.Floor(z))
                            {
                                bimage.SetPixel(x, y, Color.FromArgb(0, 255, 255));
                            }
                        }
                        else if (cX == false)
                        {
                            if (x1 == x)
                            {
                                bimage.SetPixel(x, y, Color.FromArgb(0, 255, 255));
                            }
                        }
                        else if (cY == false)
                        {
                            if (y1 == y)
                            {
                                bimage.SetPixel(x, y, Color.FromArgb(0, 255, 255));
                            }
                        }
                        
                    }
                }
                
                foreach (Point p in AryPoint[i].Points)
                {
                    if (p.IsEmpty)
                    {
                        break;
                    }
                    else
                    {
                        int iLight = 0;
                        bimage.SetPixel(p.X, p.Y, Color.FromArgb(iLight, 255, 255));
                    }
                }       
               
            }               
            TargetImage = bimage;
            return TargetImage;
        }
        public Image HoughTransform(Image SourceImage, int iThreshold)
        {
            Image TargetImage = SourceImage;
            int height = SourceImage.Height;
            int width = SourceImage.Width;
            Bitmap bimage = new Bitmap(width, height);

            try
            {
                int[, ,] rgbDataA = getRGBData(SourceImage);

                _aryMy = new MyClass[width, height];              
                double pmax = Math.Sqrt(((width / 2) * (width / 2)) + ((height / 2) * (height / 2)));
                double tmax = Math.PI * 2;

                double dp = pmax / (double)width;
                double dt = tmax / (double)height;

                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        int point = rgbDataA[x, y, 0];
                        //點是白點才算 (門檻)
                        if (point >= iThreshold)
                        {
                            for (int j = 0; j < height; j++)
                            {
                                // R = X‧SinQ + Y‧CosQ
                                double r = ((double)(x - (width / 2)) * Math.Cos(dt * (double)j)) + ((double)(y - (height / 2)) * Math.Sin(dt * (double)j));

                                int k = (int)((r / pmax) * width);
                                if (k >= 0 && k < width)
                                {
                                    if (_aryMy[k, j] == null)
                                    {
                                        _aryMy[k, j] = new MyClass();
                                    }
                                    _aryMy[k, j].AddPoint(x, y);
                                }
                            }
                        }
                    }
                }

                //找出最高的點.. 給算權重用
                int iPointMax = 0;
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        if (_aryMy[x, y] != null)
                        {
                            if (_aryMy[x, y].Counts > iPointMax)
                            {

                                iPointMax = _aryMy[x, y].Counts;
                            }
                        }
                    }
                }
                // 讓曲線能依交點數量呈現, 出比重,越白越多交點
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        int iLight = 0;
                        if (iPointMax != 0 )
                        {
                            if (_aryMy[x, y] != null)
                            {
                                iLight = (int)(((double)_aryMy[x, y].Counts / (double)iPointMax) * 255.0);
                            }
                            else {
                                iLight = 0;
                            }
                        }
                        bimage.SetPixel(x, y, Color.FromArgb(iLight, iLight, iLight));
                    }
                }
                
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            TargetImage = bimage;
            return TargetImage;
        }

        public int LimitValue(int iValue)
        {
            if (iValue > iMax)
            {
                iValue = iMax;
            }
            else if (iValue < iMin)
            {
                iValue = iMin;
            }
            return iValue;
        }

        public Image ImagePlusImage(Image ImageA, Image ImageB)
        {
            // iFilter = 0:Red 1:Green 2:Blue
            Image TargetImage = ImageA;
            int[, ,] rgbDataA = getRGBData(ImageA);
            int[, ,] rgbDataB = getRGBData(ImageB);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int iRed = (rgbDataA[x, y, 0] + rgbDataB[x, y, 0]);
                    int iGreen = (rgbDataA[x, y, 1] + rgbDataB[x, y, 1]);
                    int iBlue = (rgbDataA[x, y, 2] + rgbDataB[x, y, 2]);
                    
                    iRed = LimitValue(iRed);
                    iGreen = LimitValue(iGreen);
                    iBlue = LimitValue(iBlue);

                    bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                }
            }

            TargetImage = bimage;
            return TargetImage;
        }


        public Image ImageMinusImage(Image ImageA, Image ImageB)
        {
            // iFilter = 0:Red 1:Green 2:Blue
            Image TargetImage = ImageA;
            int[, ,] rgbDataA = getRGBData(ImageA);
            int[, ,] rgbDataB = getRGBData(ImageB);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int iRed = (rgbDataA[x, y, 0] - rgbDataB[x, y, 0]);
                    int iGreen = (rgbDataA[x, y, 1] - rgbDataB[x, y, 1]);
                    int iBlue = (rgbDataA[x, y, 2] - rgbDataB[x, y, 2]);

                    iRed = LimitValue(iRed);
                    iGreen = LimitValue(iGreen);
                    iBlue = LimitValue(iBlue);

                    bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                }
            }
            TargetImage = bimage;
            return TargetImage;
        }

        public Image ImageDiffImage(Image ImageA, Image ImageB)
        {
            // iFilter = 0:Red 1:Green 2:Blue
            Image TargetImage = ImageA;
            int[, ,] rgbDataA = getRGBData(ImageA);
            int[, ,] rgbDataB = getRGBData(ImageB);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int Value = 0;
                    int Value2= 0;

                    Value = rgbDataA[x, y, 0] ;
                    Value2 = rgbDataB[x, y, 0];
                    
                    if(Value != Value2 )
                    {
                        bimage.SetPixel(x, y, Color.FromArgb(iMin, iMin, iMin));
                    }
                    else
                    {
                        bimage.SetPixel(x, y, Color.FromArgb(iMax, iMax, iMax)); 
                    }

                    
                }
            }
            TargetImage = bimage;
            return TargetImage;
        }

        public Image ImageMultiplyImage(Image ImageA, Image ImageB)
        {
            // iFilter = 0:Red 1:Green 2:Blue
            Image TargetImage = ImageA;
            int[, ,] rgbDataA = getRGBData(ImageA);
            int[, ,] rgbDataB = getRGBData(ImageB);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int iRed =   (rgbDataA[x, y, 0] + rgbDataB[x, y, 0] ) / 2;
                    int iGreen = (rgbDataA[x, y, 1] + rgbDataB[x, y, 1] ) / 2;
                    int iBlue =  (rgbDataA[x, y, 2] + rgbDataB[x, y, 2] ) / 2;
                    bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                }
            }

            TargetImage = bimage;
            return TargetImage;
        }

        public Image ImageMultiplyImage2(Image ImageA, Image ImageB)
        {
            // iFilter = 0:Red 1:Green 2:Blue
            Image TargetImage = ImageA;
            int[, ,] rgbDataA = getRGBData(ImageA);
            int[, ,] rgbDataB = getRGBData(ImageB);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int iRed = (rgbDataA[x, y, 0] * rgbDataB[x, y, 0]) / 255;
                    int iGreen = (rgbDataA[x, y, 1] * rgbDataB[x, y, 1]) / 255;
                    int iBlue = (rgbDataA[x, y, 2] * rgbDataB[x, y, 2]) / 255;

                    bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                }
            }

            TargetImage = bimage;
            return TargetImage;
        }

        public Image DoSomething(Image ImageA,Image ImageB)
        {
            // iFilter = 0:Red 1:Green 2:Blue
            Image TargetImage = ImageA;
            int[, ,] rgbDataA = getRGBData(ImageA);
            int[, ,] rgbDataB = getRGBData(ImageB);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;
            int iRed, iGreen, iBlue;
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int iRedA = rgbDataA[x, y, 0];
                    int iGreenA = rgbDataA[x, y, 1];
                    int iBlueA = rgbDataA[x, y, 2];

                    int iRedB = rgbDataB[x, y, 0];
                    int iGreenB = rgbDataB[x, y, 1];
                    int iBlueB = rgbDataB[x, y, 2];

                    double dRed = Math.Round(((double)iRedA / 255), 0);
                    double dGreen = Math.Round(((double)iGreenA / 255), 0);
                    double dBlue = Math.Round(((double)iBlueA / 255), 0);


                    iRed = (int)((double)iRedB * dRed);
                    iGreen = (int)((double)iGreenB * dGreen);
                    iBlue = (int)((double)iBlueB * dBlue);

                    iRed = LimitValue(iRed);
                    iGreen = LimitValue(iGreen);
                    iBlue = LimitValue(iBlue);
                    bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));                
                }
            }

            TargetImage = bimage;
            return TargetImage;
        }


        public Image DoWithSobleFilter(Image SourceImage)
        {
            Image TargetImage = SourceImage;
            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;
 
            int[] iColor = new int[3];
            iColor[0] = 0;
            iColor[1] = 0;
            iColor[2] = 0;

            int iZ1 = 0;
            int iZ2 = 0;
            int iZ3 = 0;
            int iZ4 = 0;
            int iZ5 = 0; 
            int iZ6 = 0;
            int iZ7 = 0;
            int iZ8 = 0;
            int iZ9 = 0;
         
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    //RGB
                    for (int z = 0; z < 3; z++)
                    {
                        if ((x - 1) > 0 && (y - 1) > 0 && (x + 1) < width && (y + 1) < height)
                        {
                            iZ1 = rgbData[ x-1, y-1, z];
                            iZ2 = rgbData[ x  , y-1, z];
                            iZ3 = rgbData[ x+1, y-1, z];
                            iZ4 = rgbData[ x-1,   y, z];
                            iZ5 = rgbData[ x  ,   y, z];
                            iZ6 = rgbData[ x+1,   y, z];   
                            iZ7 = rgbData[ x-1, y+1, z];   
                            iZ8 = rgbData[ x  , y+1, z];   
                            iZ9 = rgbData[ x+1, y+1, z];   
                            iColor[z] = Math.Abs( (iZ7+2*iZ8+iZ9)-(iZ1+2*iZ2+iZ3)) + Math.Abs((iZ3+2*iZ6+iZ9)-(iZ1+2*iZ4+iZ7));
                        }
                        else
                        {
                            iColor[z] = rgbData[x, y, z];  
                        }

                        iColor[z] = LimitValue(iColor[z]);
                    }

                    
                    bimage.SetPixel(x, y, Color.FromArgb(iColor[0], iColor[1], iColor[2]));
                }
            }

            TargetImage = bimage;

            return TargetImage;
        }

        public Image DoErosionWithFilter(Image SourceImage, int[,] Filter)
        {
            Image TargetImage = SourceImage;
            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;
            
            int iffx = Filter.GetLength(0);
            int iffy = Filter.GetLength(1);
            int ifTotal = iffx * iffy;
            int qx = -iffx / 2;
            int qy = -iffy / 2;

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    int iIn = 0;
                    int iOut = 0;

                    for (int ifx = 0; ifx < iffx; ifx++)
                    {
                        for (int ify = 0; ify < iffy; ify++)
                        {
                            int rx = x + ifx + qx;
                            int ry = y + ify + qy;
                            int Value = 0;
                            
                            if (rx >= 0 && ry >= 0 && rx < width && ry < height)
                            {
                                Value = rgbData[rx, ry, 0];

                                if (Value == 0)
                                {
                                    iIn++;
                                }
                                else 
                                {
                                    iOut++;
                                }
                            }
                            else 
                            {
                                iOut++;
                            }
                        }
                    }

                    if (ifTotal == (iOut + iIn))
                    {
                        if (iOut > 0)
                        {
                            bimage.SetPixel(x, y, Color.FromArgb(iMin, iMin, iMin));
                        }
                        else
                        {
                            bimage.SetPixel(x, y, Color.FromArgb(iMax, iMax, iMax));
                        }
                    }
                }
            }

            TargetImage = bimage;

            return TargetImage;
        }

        public Image DoWithFilter(Image SourceImage, int[,] Filter)
        {
            Image TargetImage = SourceImage;
            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;

            int iffx = Filter.GetLength(0);
            int iffy = Filter.GetLength(1);
            int qx = -iffx / 2;
            int qy = -iffy / 2;

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    int iRed = 0;
                    int iGreen = 0;
                    int iBlue = 0;
                    int iWeight = 0;

                    for (int ifx = 0; ifx < iffx; ifx++)
                    {
                        for (int ify = 0; ify < iffy; ify++)
                        {
                            int rx = x + ifx + qx;
                            int ry = y + ify + qy;
                            int Red = 0;
                            int Green = 0;
                            int Blue = 0;

                            if (rx >= 0 && ry >= 0 && rx < width && ry < height)
                            {
                                Red = rgbData[rx, ry, 0];
                                Green = rgbData[rx, ry, 1];
                                Blue = rgbData[rx, ry, 2];

                                iRed += Red * Filter[ifx, ify];
                                iGreen += Green * Filter[ifx, ify];
                                iBlue += Blue * Filter[ifx, ify];
                                iWeight += Filter[ifx, ify];
                            }
                        }                        
                    }

                    if (iWeight == 0)
                    {
                        iWeight = 1;
                    }
                    iRed = System.Math.Abs(iRed);
                    iGreen = System.Math.Abs(iGreen);
                    iBlue = System.Math.Abs(iBlue);

                    iRed = iRed / iWeight;               
                    iGreen = iGreen / iWeight;
                    iBlue = iBlue / iWeight;

                    iRed = LimitValue(iRed);
                    iGreen = LimitValue(iGreen);
                    iBlue = LimitValue(iBlue);

                    bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                }
            }

            TargetImage = bimage;

            return TargetImage;
        }
        
        public Image Perspective(Image SourceImage)
        {
            Image TargetImage = null;
            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap oldbiImage = new Bitmap(SourceImage);

            //old Image
            //Top Left
            Point A = new Point();  
            A.X = 140; A.Y = 40;

            //Top Right
            Point B = new Point();
            B.X = 574; B.Y = 40;

            //Bottom Left
            Point C = new Point();
            C.X = 30; C.Y = 620;
                        
            //Bottom Right
            Point D = new Point();
            D.X = 700; D.Y = 610;

            Point[] aryPoint = new Point[] { A, B, C, D };

            //原座標為 580,670 ..
            Bitmap newbimage = new Bitmap(1000, 1000);

            int oWidht = oldbiImage.Width;
            int oHeight = oldbiImage.Height;

            int nWidth = newbimage.Width;
            int nHeight = newbimage.Height;

            // c4 , c8 可調整 基準點 0.0  (各再異動 40 像素..才看得到邊..

            double c1 = (double)((double)(574 - 140) / 670);
            double c2 = (double)((double)(30 - 140) / 580);
            double c3;
            double c4 = (double)140 -40;
            double c5 = (double)0;
            double c6 = (double)((double)(620 - 40) / 580);
            double c7;
            double c8 = (double)40 -40;

            c3 = (double)((double)(700 - c4 - (670 * c1) - (580 * c2)) / 388600);
            c7 = (double)((double)(610 - c8 - (670 * c5) - (580 * c6)) / 388600);

            int iRed,iGreen,iBlue;
            
            int[] p1 = null;
            int[] p2 = null;
            int[] p3 = null;
            int[] p4 = null;
            

            double dx, dy;

            //inverse  mapping
            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                     // eight parameter 
                    dx = (c1 * x) + (c2 * y) + (c3 * x * y) + c4;
                    dy = (c5 * x) + (c6 * y) + (c7 * x * y) + c8;


                    /* Bilinear */
                    PointF P1, P2, P3, P4;                    
                    double dw, dh, ddw, ddh;
                    /*        dw      (1-dw)
                     *  P1   ____ R1        P2
                     *   | dh    
                     *   |      (dx,dy)
                     *   |  (1-dh)
                     *  P3        R2        P4                                                               
                    */

                    
                    int tmpX, tmpY;
                    tmpX = (int)Math.Floor(dx);
                    tmpY = (int)Math.Floor(dy);

                    //超出原圖座標點的不要抓顏色
                    if (tmpX >= 0 && tmpY >= 0 && (tmpX + 1 < oWidht)  && tmpY < oHeight)
                    {
                        P1 = new PointF(tmpX, tmpY);
                        P2 = new PointF(tmpX + 1, tmpY);
                        P3 = new PointF(tmpX, tmpY + 1);
                        P4 = new PointF(tmpX + 1, tmpY + 1);
                        dw = dx - tmpX;
                        dh = dy - tmpY;
                        ddw = 1 - dw;
                        ddh = 1 - dh;

                        p1 = new int[3] { rgbData[tmpX, tmpY, 0], rgbData[tmpX, tmpY, 1], rgbData[tmpX, tmpY, 2] };
                        p2 = new int[3] { rgbData[tmpX + 1, tmpY, 0], rgbData[tmpX + 1, tmpY, 1], rgbData[tmpX + 1, tmpY, 2] };
                        p3 = new int[3] { rgbData[tmpX, tmpY + 1, 0], rgbData[tmpX, tmpY + 1, 1], rgbData[tmpX, tmpY + 1, 2] };
                        p4 = new int[3] { rgbData[tmpX + 1, tmpY + 1, 0], rgbData[tmpX + 1, tmpY + 1, 1], rgbData[tmpX + 1, tmpY + 1, 2] };

                        double iR1, iR2;
                        iR1 = (dw * p1[0]) + (ddw * p2[0]);
                        iR2 = (dw * p3[0]) + (ddw * p4[0]);
                        iRed = Convert.ToInt32((dh * iR1) + (ddh * iR2));

                        // G
                        double iG1, iG2;
                        iG1 = (dw * p1[1]) + (ddw * p2[1]);
                        iG2 = (dw * p3[1]) + (ddw * p4[1]);
                        iGreen = Convert.ToInt32((dh * iG1) + (ddh * iG2));

                        // B
                        double iB1, iB2;
                        iB1 = (dw * p1[2]) + (ddw * p2[2]);
                        iB2 = (dw * p3[2]) + (ddw * p4[2]);
                        iBlue = Convert.ToInt32((dh * iB1) + (ddh * iB2));

                        if (iRed < 0 || iRed > 255)
                        {
                            iRed = 0;
                        }
                        if (iGreen < 0 || iGreen > 255)
                        {
                            iGreen = 0;
                        }
                        if (iBlue < 0 || iBlue > 255)
                        {
                            iBlue = 0;
                        }

                        newbimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                    }
                }
            }
            
            TargetImage = newbimage;
            return TargetImage;
        }

        public Image Bilinear(Image SourceImage)
        {
            // Bilinear Interpolation
            Image TargetImage = null;
            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap oldbiImage = new Bitmap(SourceImage);
            Bitmap newbimage = new Bitmap(oldbiImage.Width *2, oldbiImage.Height *2);

            int oWidht = oldbiImage.Width;
            int oHeight = oldbiImage.Height;

            int nWidth = newbimage.Width;
            int nHeight = newbimage.Height;

            /* 沒換轉型會變 0
             * 縮放比例 (倒過來..因為 使用Inverse Mapping ) 
             * 放大兩倍= 0.5  ,縮小減半 = 2                    
             */
            double nWidthDiff = (double)oWidht / nWidth;
            double nHeightDiff = (double)oHeight / nHeight;
            
            double fx, fy, nx, ny;  
            int cx, cy, fr_x, fr_y;

            int[] p1 = null;
            int[] p2 = null;
            int[] p3 = null;
            int[] p4 = null;

            //inverse mapping
            for (int dx = 0; dx < nWidth; dx++)
            {
                for (int dy = 0; dy < nHeight; dy++)
                {
                    //座標  
                    fr_x = (int)Math.Floor(dx * nWidthDiff);
                    fr_y = (int)Math.Floor(dy * nHeightDiff);

                    cx = fr_x + 1;
                    if (cx >= oWidht) 
                        cx = fr_x;

                    cy = fr_y + 1;
                    if (cy >= oHeight) 
                        cy = fr_y;

                    //與作標的差異 (權重)
                    fx = dx * nWidthDiff - fr_x;
                    fy = dy * nHeightDiff - fr_y;
                    nx = 1.0 - fx;
                    ny = 1.0 - fy;                    

                    // 四點
                    // p1   p2
                    //    *
                    // p3   p4
                    p1 = new int[3] {rgbData[fr_x, fr_y,0], rgbData[fr_x, fr_y,1], rgbData[fr_x, fr_y,2]};
                    p2 = new int[3] {rgbData[cx, fr_y,0], rgbData[cx, fr_y,1], rgbData[cx, fr_y,2]};
                    p3 = new int[3] {rgbData[fr_x, cy,0], rgbData[fr_x, cy,1], rgbData[fr_x, cy,2]};
                    p4 = new int[3] {rgbData[cx, cy,0], rgbData[cx, cy,1], rgbData[cx, cy,2]};

                    //再各兩點取中間
                    // p1  R1   p2
                    // p3  R2   p4
                    // (1-fy)*R1 + (fy)*R2 
                    // R G B 各作一次..
                    double iR1, iR2;
                    int iRed;
                    iR1 = (nx * p1[0]) + (fx * p2[0] );
                    iR2 = (nx * p3[0]) + (fx * p4[0] );
                    iRed = Convert.ToInt32((ny*iR1) + (fy*iR2));

                    // G
                    double iG1, iG2;
                    int iGreen;
                    iG1 = (nx * p1[1]) + (fx * p2[1] );
                    iG2 = (nx * p3[1]) + (fx * p4[1] );
                    iGreen = Convert.ToInt32((ny*iG1)  + (fy*iG2));
                    
                    // B
                    double iB1, iB2;
                    int iBlue;
                    iB1 = (nx * p1[2]) + (fx * p2[2] );
                    iB2 = (nx * p3[2]) + (fx * p4[2] );
                    iBlue = Convert.ToInt32((ny*iB1)  + (fy*iB2));    

                    //寫回Image
                    newbimage.SetPixel(dx, dy, Color.FromArgb(iRed,iGreen ,iBlue ) );

                }
            }

            TargetImage = newbimage;
            return TargetImage;
        }

        public Image EmptyImage(Image SourceImage)
        {
            Image TargetImage = SourceImage;
            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {                    
                    bimage.SetPixel(x, y, Color.FromArgb(0, 0, 0));
                }
            }

            TargetImage = bimage;
            return TargetImage;
        }

        public Image ColorFilter(Image SourceImage ,int iFilter)
        {
            // iFilter = 0:Red 1:Green 2:Blue
            Image TargetImage = SourceImage;
            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int iRed = rgbData[x, y, 0];
                    int iGreen = rgbData[x, y, 1];
                    int iBlue = rgbData[x, y, 2];
                    switch (iFilter)
                    { 
                        case 0:
                            iGreen = 0;
                            iBlue = 0;
                            bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                            break;
                        case 1:
                            iRed = 0;
                            iBlue = 0;
                            bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                            break;
                        case 2:
                            iRed = 0;
                            iGreen = 0;
                            bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                            break;
                        default:
                            break;
                    }
                }
            }

            TargetImage = bimage;
            return TargetImage;
        }

        public Image Invert(Image SourceImage)
        {
            Image TargetImage = SourceImage;
            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int iRed = 255-rgbData[x, y, 0] ;
                    int iGreen = 255-rgbData[x, y, 1];
                    int iBlue = 255 - rgbData[x, y, 2];
                    bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                }
            }

            TargetImage = bimage;
            return TargetImage;
        }

        public Image doBinary(Image SourceImage,int Value)
        {
            Image TargetImage = SourceImage;

            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int iValue = rgbData[x, y, 0];

                    if (iValue >= Value)
                    {
                        bimage.SetPixel(x, y, Color.FromArgb(255, 255, 255));
                    }
                    else 
                    {
                        bimage.SetPixel(x, y, Color.FromArgb(0, 0, 0));
                    }
                }
            }
            TargetImage = bimage;
            return TargetImage;
        }

        public Image doGray(Image SourceImage)
        {
            Image TargetImage = SourceImage;

            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int iAvg = ((rgbData[x, y, 0] + rgbData[x, y, 1] + rgbData[x, y, 2]) / 3);
                    bimage.SetPixel(x,y,Color.FromArgb(iAvg,iAvg,iAvg));
                }
            }
            TargetImage = bimage;
            return TargetImage;
        }

        public Image forHW3(Image SourceImage)
        {
            Image TargetImage = SourceImage;
            int[, ,] rgbData = getRGBData(SourceImage);

            Bitmap bimage = new Bitmap(TargetImage);
            int height = bimage.Height;
            int width = bimage.Width;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int iRed = rgbData[x, y, 0];
                    int iGreen = rgbData[x, y, 1];
                    int iBlue = rgbData[x, y, 2];


                    if (iGreen < 127)
                    {
                        iGreen = iGreen * 2;                        
                    }
                    else 
                    {
                        iGreen = (255 - iGreen) * 2;
                    }
                    iGreen = LimitValue(iGreen);
                    iBlue = (255 - iBlue);

                    bimage.SetPixel(x, y, Color.FromArgb(iRed, iGreen, iBlue));
                }
            }
            TargetImage = bimage;
            return TargetImage;
        }
        // R:0 G:1 B:2
        public int[, ,] getRGBData(Image gImage)
        {
            Bitmap bimage = new Bitmap(gImage);
            Int64 iHeight = bimage.Height;
            Int64 iWidth = bimage.Width;
            int[, ,] rgbData = new int[iWidth, iHeight, 3];

            for (int y = 0; y < iHeight; y++)
            {
                for (int x = 0; x < iWidth; x++)
                {
                    Color color = bimage.GetPixel(x, y);
                    rgbData[x, y, 0] = color.R;
                    rgbData[x, y, 1] = color.G;
                    rgbData[x, y, 2] = color.B;                    
                }
            }
            return rgbData;
        }

        #endregion 

        #region Event 

        private void btnUseNewImage_Click(object sender, EventArgs e)
        {
            this.pictureBox1.Image = this.pictureBox2.Image;
            Init();
            MessageBox.Show("Done!");
        }

        private void btnINIT_Click(object sender, EventArgs e)
        {
            this.pictureBox2.Image = _CurrentImage;
            MessageBox.Show("Done!");
        }

        private void btnGray_Click(object sender, EventArgs e)
        {
            this.pictureBox2.Image = doGray(_CurrentImage);
            MessageBox.Show("Done!");
        }

        private void btnClean_Click(object sender, EventArgs e)
        {
            this.pictureBox2.Image = null;
            MessageBox.Show("Done!");
        }

        private void Load_Click(object sender, EventArgs e)
        {
            try
            {                
                OpenFileDialog open = new OpenFileDialog();
                open.Filter = "Image Files(*.jpg; *.jpeg; *.gif; *.bmp; *.png)|*.jpg; *.jpeg; *.gif; *.bmp; *.png";
                //open.InitialDirectory = ".";
                if (open.ShowDialog() == DialogResult.OK)
                {
                    pictureBox1.Image = new Bitmap(open.FileName);
                    Init();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                //throw new ApplicationException("Failed loading image");
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            //this.pictureBox2.Image.Save(@"Result.bmp", ImageFormat.Bmp);
            string sSaveFN;

            SaveFileDialog save = new SaveFileDialog();
            save.Filter = "Image Files(*.jpg; *.jpeg; *.gif; *.bmp; *.png)|*.jpg; *.jpeg; *.gif; *.bmp; *.png";
            if (save.ShowDialog() == DialogResult.OK)
            {
                sSaveFN = save.FileName;
                this.pictureBox2.Image.Save(sSaveFN, ImageFormat.Bmp);
                MessageBox.Show("Done!");
            }            
        }

        private void btnInvert_Click(object sender, EventArgs e)
        {
            this.pictureBox2.Image = Invert(_CurrentImage);
            MessageBox.Show("Done!");
        }

        private void btnRedFilter_Click(object sender, EventArgs e)
        {
            this.pictureBox2.Image = ColorFilter(_CurrentImage, 0);
            MessageBox.Show("Done!");
        } 

        private void btnGreenFilter_Click(object sender, EventArgs e)
        {
            this.pictureBox2.Image = ColorFilter(_CurrentImage, 1);
            MessageBox.Show("Done!");
        }

        private void btnBlueFilter_Click(object sender, EventArgs e)
        {
            this.pictureBox2.Image = ColorFilter(_CurrentImage, 2);
            MessageBox.Show("Done!");
        }

        private void btnEmpty_Click(object sender, EventArgs e)
        {
            this.pictureBox2.Image = EmptyImage(_CurrentImage);
            MessageBox.Show("Done!");
        }

        private void btnReSize_Click(object sender, EventArgs e)
        {
            this.pictureBox2.Image = Bilinear(_CurrentImage);
            MessageBox.Show("Done!");
        }

        private void btnPerspective_Click(object sender, EventArgs e)
        {
            this.pictureBox2.Image = Perspective(_CurrentImage);
            MessageBox.Show("Done!");
        }

        private void btnFilter_Click(object sender, EventArgs e)
        {
            SetFilter();
            this.pictureBox2.Image = DoWithFilter(_CurrentImage, iFilter);
            MessageBox.Show("Done!");
        }

        private void btnDoFilter_Click(object sender, EventArgs e)
        {
            Image MyImage = _CurrentImage;
            int[,] Filter;

            Filter = GetFilter_Sharpen5();
            MyImage = DoWithFilter(MyImage, Filter);

            /*
            Filter = GetFilter_SobelX();
            MyImage = DoWithFilter(MyImage, Filter);

            Filter = GetFilter_Blur_5();
            MyImage = DoWithFilter(MyImage, Filter);
            */
            this.pictureBox2.Image = MyImage;
            MessageBox.Show("Done!");

        }

        


        private void btnDoSomething_Click(object sender, EventArgs e)
        {
            Image MyImage = _CurrentImage;
            MyImage = DoSomething(MyImage, _CurrentImage);
            this.pictureBox2.Image = MyImage;
            MessageBox.Show("Done!");
        }

        private void btnSobel_Click(object sender, EventArgs e)
        {
            Image TargetImage;
            /*
            Image ImageA;
            Image ImageB;
            int[,] Filter;

            
            Filter = GetFilter_SobelX();
            ImageA = DoWithFilter(_CurrentImage, Filter);

            Filter = GetFilter_SobelY();
            ImageB = DoWithFilter(_CurrentImage, Filter);

            TargetImage = ImageMultiplyImage(ImageA, ImageB);
            */
            TargetImage = DoWithSobleFilter(_CurrentImage);
            this.pictureBox2.Image = TargetImage;
            MessageBox.Show("Done!");
        }

        private void btnBlur_Click(object sender, EventArgs e)
        {
            Image TargetImage;
            int[,] Filter;

            Filter = GetFilter_Blur_5();
            TargetImage = DoWithFilter(_CurrentImage, Filter);

            this.pictureBox2.Image = TargetImage;
            MessageBox.Show("Done!");
        }

        private void btnSharpened_Click(object sender, EventArgs e)
        {
            Image TargetImage;
            int[,] Filter;

            Filter = GetFilter_Sharpen5();
            TargetImage = DoWithFilter(_CurrentImage, Filter);

            this.pictureBox2.Image = TargetImage;
            MessageBox.Show("Done!");
        }
        

        private void btnHW2_Click(object sender, EventArgs e)
        {
            int[,] Filter;

            //    Image0   // Source       原圖
            Image Image1;  // Laplacian    銳化 (未加原圖)  0     二階微分
            Image Image2;  // Sharpened    銳化 (加原圖)    0+1
            Image Image3;  // Sobel        找邊             0     一階微分
            Image Image4;  // Blur         模糊             3     模糊
            Image Image5;  // /255         正規到0~1 * 1    
            Image Image6;  // Target       5+0      

            MessageBox.Show("Image0 = Source Image"); 

            #region Image 1
            Filter = GetFilter_LaplacianFilters4();
            Image1 = DoWithFilter(_CurrentImage, Filter);
            this.pictureBox2.Image = Image1;
            MessageBox.Show("Image1 = Laplacian Mask");
            #endregion 

            #region Image 2
            Filter = GetFilter_Sharpen5();
            Image2 = DoWithFilter( _CurrentImage, Filter);
            this.pictureBox2.Image = Image2;
            MessageBox.Show("Image2 = Sharpen");
            #endregion 

            #region Image 3
            Image3 = DoWithSobleFilter(_CurrentImage);
            this.pictureBox2.Image = Image3;
            MessageBox.Show("Image3 = Soble Filter ");
            #endregion

            #region Image 4
            Filter = GetFilter_Blur_5();
            Image4 = DoWithFilter(Image3, Filter);
            this.pictureBox2.Image = Image4;
            MessageBox.Show("Image4 = Image3->Blur");
            #endregion 

            #region Image 5
            Filter = GetFilter_Blur_5();
            Image5 = DoSomething(Image4, Image1);
            this.pictureBox2.Image = Image5;
            MessageBox.Show("Image5 = (Image4 / 255) * Image1 ");
            #endregion 

            #region Image 6
            Image6 = ImagePlusImage(Image5, _CurrentImage);
            //Image6 = ImageMultiplyImage(Image5, _CurrentImage);
            this.pictureBox2.Image = Image6;
            MessageBox.Show("Image6 = Image5 + Image0 ");
            #endregion


            this.pictureBox2.Image = Image6;
            MessageBox.Show("Done!");

            this.pictureBox3.Image = _CurrentImage;
            this.pictureBox3.Image.Save(@"HW2-Image0.jpg", ImageFormat.Jpeg);
            this.pictureBox3.Image = Image1;
            this.pictureBox3.Image.Save(@"HW2-Image1.jpg", ImageFormat.Jpeg);
            this.pictureBox3.Image = Image2;
            this.pictureBox3.Image.Save(@"HW2-Image2.jpg", ImageFormat.Jpeg);
            this.pictureBox3.Image = Image3;
            this.pictureBox3.Image.Save(@"HW2-Image3.jpg", ImageFormat.Jpeg);
            this.pictureBox3.Image = Image4;
            this.pictureBox3.Image.Save(@"HW2-Image4.jpg", ImageFormat.Jpeg);
            this.pictureBox3.Image = Image5;
            this.pictureBox3.Image.Save(@"HW2-Image5.jpg", ImageFormat.Jpeg);
            this.pictureBox3.Image = Image6;
            this.pictureBox3.Image.Save(@"HW2-Image6.jpg", ImageFormat.Jpeg);

            MessageBox.Show("Save Done!");
        }                

        private void btnHW3_Click(object sender, EventArgs e)
        {
            Image TargetImage;
            Image GrayImage;

            GrayImage = doGray(_CurrentImage);
            this.pictureBox2.Image = GrayImage;
            MessageBox.Show("Gray Image");


            TargetImage = forHW3(GrayImage);
            this.pictureBox2.Image = TargetImage;
            MessageBox.Show("Done!");
        }

        private void btnHW4_Click(object sender, EventArgs e)
        {

            string sThreshold = txtHW4.Text;

            int iTS = 0;
            try
            {
                iTS = Convert.ToInt16(sThreshold);
                iTS = LimitValue(iTS);
            }
            catch 
            {
                iTS = 120;
                MessageBox.Show("Default Threshold as 120");
            }

            Image TargetImage;            
            Image GrayImage;
            Image BinaryImage;
            Image ErosionImage;
            int[,] Filter;

            GrayImage = doGray(_CurrentImage);
            this.pictureBox2.Image = GrayImage;
            MessageBox.Show("Gray Image");

            BinaryImage = doBinary(GrayImage, iTS);
            this.pictureBox2.Image = BinaryImage;
            MessageBox.Show("Binary Image");                        
            
            Filter = GetFilter_Blur_3();
            ErosionImage = DoErosionWithFilter(BinaryImage, Filter);
            this.pictureBox2.Image = ErosionImage;
            MessageBox.Show("Erosion Image with Threshold as " +  iTS.ToString() );

            TargetImage = ImageDiffImage(BinaryImage, ErosionImage);
            this.pictureBox2.Image = TargetImage;
            MessageBox.Show("Done!");
            
        }

        private void btnHW5_Click(object sender, EventArgs e)
        {            
            Image TargetImage;

            string sThreshold = txtHW4.Text;
            int iTS = 0;
            try
            {
                iTS = Convert.ToInt16(sThreshold);
                iTS = LimitValue(iTS);
            }
            catch
            {
                iTS = 200;
                MessageBox.Show("Default Threshold as 200");
            }

            TargetImage = HoughTransform(_CurrentImage, iTS);
            this.pictureBox2.Image = TargetImage;            
            this.pictureBox3.Image = TargetImage;
            this.pictureBox3.Image.Save(@"HW5-Image1.bmp", ImageFormat.Bmp);
            MessageBox.Show("Print Hough Transform");

            string sFindLine = txtHW5.Text;
            int iFindLine = 0;
            try
            {
                iFindLine = Convert.ToInt16(sFindLine);               
            }
            catch
            {
                iFindLine = 5;
                MessageBox.Show("Default Find 5 Line");
            }
            TargetImage = PrintLineByTopN(_CurrentImage, iFindLine);
            this.pictureBox2.Image = TargetImage;
            this.pictureBox3.Image = TargetImage;
            this.pictureBox3.Image.Save(@"HW5-Image2.bmp", ImageFormat.Bmp);
            MessageBox.Show("Print Line By Top " + iFindLine.ToString() );            
        }
        #endregion

      
    }



}
